#pragma once
#include <vector>
#include <unordered_map>
#include <algorithm>

#include "constants.h"
#include "classes.h"
#include "tools.h"
#include "optimizer_tools.h"

using namespace std;

class OptRadical
{
public:
    vector<vector<BwType>> edge_site_bw_type_vec;
    vector<BwType> center_site_bw_type_vec;
    int edge_site_low_bw[MAX_N];
    int edge_site_high_bw[MAX_N];
    long long center_site_low_bw;
    long long center_site_high_bw;
    AssignInfo *assign_info;
    int edge_low_index;
    int edge_hight_index;
    int center_low_index;
    int center_hight_index;
    double total_score;
    double edge_site_score;
    double center_site_score;
    int success_count;
    int skip_diff_sum;

    OptRadical(AssignInfo &assign_info);
    void opt(double edge_low_quantile, double edge_hight_quantile, double center_low_quantile, double center_hight_quantile, int skip_diff_sum);

private:
    void opt_t(int t);
    void opt_t_big_site(int t, TAssign *tassign, int site_id);
    bool opt_t_big_site_try_decrease(int t, TAssign *tassign, int site_id, int target, bool opt_inherit);
    bool opt_t_big_site_process_overflow_t(TAssign *tassign, vector<int> &bw_uppers);

    void refresh_state();
    void refresh_edge_site_state(int site_id);
    void refresh_center_site_state();
    vector<int> get_safe_bw_uppers(int t, TAssign *tassign);
};
